package com.code.chatroom.server

import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.group.DefaultChannelGroup
import io.netty.util.concurrent.GlobalEventExecutor
import java.text.SimpleDateFormat
import java.util.*

/**
 * 服务器业务处理器
 */
class ServerHandler : SimpleChannelInboundHandler<String>(){
    companion object{
        /**
         * 定义一个Channel组，管理所有的Channel
         * GlobalEventExecutor.INSTANCE 是全局的事件执行器，是一个单例
         */
        @JvmStatic
        private val channelGroup = DefaultChannelGroup(GlobalEventExecutor.INSTANCE)
    }

    private val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    /**
     * 一旦建立连接，第一个执行
     */
    override fun handlerAdded(ctx: ChannelHandlerContext) {
        // 将当前channel加入到channelGroup
        val channel = ctx.channel()
        channelGroup.add(channel)
        // 将该用户加入到聊天室的信息推送给其他在线客户端
        // 该方法会遍历 channelGroup 中的所有channel，并发送消息
        // channelGroup.writeAndFlush("\u001B[31m[系统]\u001B[36m${channel.remoteAddress()} \u001B[32m于 \u001B[34m ${sdf.format(Date())} \u001B[32m上线，当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
        channelGroup.forEach { ch ->
            if(ch == channel){
                // 是自己
                ch.writeAndFlush("\u001B[31m[系统]\u001B[33m${ch.remoteAddress()}\u001B[32m，欢迎您加入聊天室！当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
            }else{
                // 是其他人
                ch.writeAndFlush("\u001B[31m[系统]\u001B[36m${channel.remoteAddress()} \u001B[32m于 \u001B[34m ${sdf.format(Date())} \u001B[32m上线，当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
            }
        }
    }

    /**
     * 断开连接时
     */
    override fun handlerRemoved(ctx: ChannelHandlerContext) {
        val channel = ctx.channel()
        // 将用户离线的消息推送给其他在线客户端
        channelGroup.writeAndFlush("\u001B[31m[系统]\u001B[36m${channel.remoteAddress()} \u001B[32m于 \u001B[34m ${sdf.format(Date())} \u001B[31m离线\u001B[32m，当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
    }

    /**
     * 表示 channel 处于活动状态
     */
    override fun channelActive(ctx: ChannelHandlerContext) {
        // 仅在服务器端提示XX上线
        println("\u001B[31m[系统]\u001B[36m${ctx.channel().remoteAddress()}\u001B[32m 于 \u001B[34m${sdf.format(Date())}\u001B[32m 上线，当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
    }

    /**
     * 连接失效时
     */
    override fun channelInactive(ctx: ChannelHandlerContext) {
        println("\u001B[31m[系统]\u001B[36m${ctx.channel().remoteAddress()}\u001B[32m 于 \u001B[34m${sdf.format(Date())}\u001B[31m 离线\u001B[32m，当前在线人数：\u001B[33m${channelGroup.size}\u001B[0m")
    }

    /**
     * 当服务器读取到数据时
     */
    override fun channelRead0(ctx: ChannelHandlerContext, msg: String) {
        val channel = ctx.channel()
        channelGroup.forEach{ ch ->
            if(ch != channel){
                // 不是自己
                ch.writeAndFlush("\u001B[33m[用户]\u001B[36m${channel.remoteAddress()} \u001B[32m于 \u001B[34m${sdf.format(Date())} \u001B[32m说：\n$msg")
            }else{
                // 是自己，回显自己发送的消息
                ch.writeAndFlush("\u001B[33m[用户]\u001B[35m${channel.remoteAddress()} \u001B[32m于 \u001B[34m${sdf.format(Date())} \u001B[32m说：\n$msg")
            }
        }
    }

    /**
     * 发生异常时，关闭通道
     */
    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        // 关闭通道
        ctx.close()
    }
}